///////////////////////////////////////////////////////////////////////////
//
//         InfiniBand FLIT (Credit) Level OMNet++ Simulation Model
//
// Copyright (c) 2004-2013 Mellanox Technologies, Ltd. All rights reserved.
// This software is available to you under the terms of the GNU
// General Public License (GPL) Version 2, available from the file
// COPYING in the main directory of this source tree.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
///////////////////////////////////////////////////////////////////////////
#ifndef __IB_MODEL_AR_PKTFWD_H_
#define __IB_MODEL_AR_PKTFWD_H_

#include <omnetpp.h>
#include "cluster/messages/messages_m.h"
#include "ib_m.h"

//
// The packet forwarder is responsible for output port selection
//
class Pktfwd : public omnetpp::cSimpleModule
{
public:

  // parameters
  bool is_cross_connected; // true indicates the current switch is cross_connected to it's upper level switch
  bool is_HD_mode; // true indicates the reduce algorithm is butterfly
  unsigned int numPorts;          // number of switch ports

  // only used in a cross-connected network
  unsigned int total_level_switch; //level of switch where it is cross-connected with the upper layer
  unsigned int cur_switch_index; // index of current switch (counted on a level basis, restarted for every new level)
  unsigned int cross_connected_upperlevel_numswitch; // num of switch on the upper level of cross-connected layer

  // state
  std::map<int,int> routingtable; // deterministic routing out port by dlid from vec file
  cModule* switch_;

private:
  virtual void handleMessage(omnetpp::cMessage *msg);

public:
  // get the output port for the given LID
  virtual int getOutputPort(IBDataMsg *p_dataMsg);
  
  // report queuing of flits on TQ for DLID (can be negative for arb)
  virtual int repQueuedFlits(unsigned int rq, unsigned int tq, unsigned int dlid, int numFlits);

  // handle a report about port loading and unloading
  virtual void handleTQLoadMsg(unsigned int tq, unsigned int srcRank, unsigned int fitstLid, unsigned int lastLid, int load);

protected:
    virtual void initialize();
    virtual void finish();
	 ~Pktfwd();
};

#endif